package net.example.lesson4;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.concurrent.CopyOnWriteArrayList;

public class TestIteratorFailFast {
    /**
     * 单线程测试
     */
    public void test() {
        try {
            // 测试迭代器的remove方法修改集合结构不会触发ConcurrentModificationException异常
            ItrRemoveTest();
            System.out.println("----分割线----");
            // 测试集合的remove方法修改集合结构会触发ConcurrentModificationException异常
            ListRemoveTest();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 测试迭代器的remove方法修改集合结构不会触发ConcurrentModificationException异常
    private void ItrRemoveTest() {
        List<String> list = new ArrayList<String>();
        list.add("1");
        list.add("2");
        list.add("3");
        ListIterator<String> itr = list.listIterator();
        while (itr.hasNext()) {
            System.out.println(itr.next());
            // 迭代器的remove方法修改集合结构
            itr.remove();
        }
    }

    // 测试集合的remove方法修改集合结构会触发ConcurrentModificationException异常
    private void ListRemoveTest() {
        List<String> list = new ArrayList<String>();
        list.add("1");
        list.add("2");
        list.add("3");
        ListIterator<String> itr = list.listIterator();
        while (itr.hasNext()) {
            System.out.println(itr.next());
            list.remove("3");
        }
    }

    public static void main(String[] args) {
        TestIteratorFailFast test1 = new TestIteratorFailFast();

        //测试触发fail-fast
//        test1.test();

        // 测试多线程操作访问list的结果
//         test1.test2();

        //测试避免fail-fast
         test1.test3();
    }

    private static List<String> list = new ArrayList<String>();

    /**
     * 多线程测试.
     */
    public void test2() {

        list.add("1");
        list.add("2");
        list.add("3");

        // 同时启动两个线程对list进行操作！
        new ErgodicThread().start();
        new ModifyThread().start();

    }

    /**
     * 如何避免fail-fast.
     * CopyOnWriteArrayList的fail-fast测试
     */
    public void test3() {
        try {
            List<String> list = new CopyOnWriteArrayList<String>();
            list.add("1");
            list.add("2");
            list.add("3");
            ListIterator<String> itr = list.listIterator();
            while (itr.hasNext()) {
                System.out.println(itr.next());
                list.add("5");
                list.remove("2");
            }
            System.out.println(list.toString());

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 遍历集合的线程
     */
    private static class ErgodicThread extends Thread {
        @Override
        public void run() {
            int i = 0;
            while (i < 10) {
                Iterator<String> iter = list.iterator();
                while (iter.hasNext()) {
                    System.out.print((String) iter.next() + ", ");
                }
                i++;
            }
        }
    }

    /**
     * 修改集合的线程
     */
    private static class ModifyThread extends Thread {
        @Override
        public void run() {
            list.add(String.valueOf("5"));
        }
    }
}